use std::cmp::Ordering;
use std::ffi::{OsStr, OsString};
use std::fmt;
use std::fmt::{Debug, Formatter};
use std::hash::{Hash, Hasher};
use std::io::Read;
use std::ops::Deref;
use std::path::PathBuf;
use crate::url::Urn;

/// 路径的核心结构体 用于封装和操作文件路径
#[derive(Clone, Default )]
pub struct Loc {
    path : PathBuf ,   // 存储实际的路径
    urn : usize ,   
    name : usize ,
}

// Send表示一个类型的所有权可以安全地从一个线程转移到另一个线程
unsafe impl Send for Loc{} 
// Sync表示一个类型可以安全地在多个线程之间通过引用共享
unsafe impl Sync for Loc{} 

impl Deref for Loc{
    type Target = PathBuf ; 
    fn deref(&self) -> &PathBuf {
        &self.path
    }
}

impl PartialEq for Loc {
    fn eq(&self,other: &Self) -> bool {
        self.path == other.path
    }
}


// Eq 是一个标记trait  表示全等性
// 如果一个类型实现了Eq  就意味着其PartialEq实现了满足自反性，对称性和传递性
impl Eq for  Loc {}  

impl PartialOrd for Loc {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}
impl Ord for Loc {
    fn cmp(&self, other: &Self) -> Ordering {
        self.path.cmp(&other.path)
    }
}

impl Hash for Loc {
    fn hash<H:Hasher> (&self , state:&mut H) {
        self.path.hash(state) 
    }
}

impl Debug for Loc {
    fn fmt(&self, f:&mut Formatter) -> fmt::Result {
        f.debug_struct("Loc") 
            .field("path" , &self.path) 
            .field("urn" , &self.urn()) 
            .field("name" , &self.name())
            .finish()
    }
}

impl Loc {
    pub fn new(path : PathBuf )-> Self {
        let Some(name) = path.file_name() else {  // else 指如果是dir的话
            let urn = path.as_os_str().len() ;
            return Self{path , urn , name:0} ;
        } ;
        let name_len = name.len() ;
        let prefix_len = unsafe{
            name.as_encoded_bytes().as_ptr().offset_from(path.as_os_str().as_encoded_bytes().as_ptr())
        } ;

        let mut bytes = path.into_os_string().into_encoded_bytes() ;
        bytes.truncate(name_len + prefix_len as usize);
        Self  {
            path : PathBuf::from(unsafe{OsString::from_encoded_bytes_unchecked(bytes)}) ,
            urn : name_len ,
            name : name_len ,
        }
    }
    
    #[inline]
    pub fn name(&self) -> &OsStr {
        unsafe {
            OsStr::from_encoded_bytes_unchecked(
                // get unchecked 不会检查是否越界
                self.bytes().get_unchecked(self.bytes().len() - self.name .. ) 
            )
        }
    }
    #[inline]
    fn bytes(&self) -> &[u8] {
        self.path.as_os_str().as_encoded_bytes()
    }
    pub fn urn(&self) -> &Urn {
        Urn::new(
            unsafe {OsStr::from_encoded_bytes_unchecked(
                self.bytes().get_unchecked(self.bytes().len() - self.urn..) 
            )}
        )
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    use std::io;
    #[test]
    fn test_loc_new() {
        let path = PathBuf::from("/example/path/to/file.txt");
        let loc = Loc::new(path.clone());
        let file_name = path.file_name().unwrap().to_str().unwrap();

        println!("{:?}" , loc) ;
        assert_eq!(loc.path, path);
        assert_eq!(loc.urn, file_name.len());
        assert_eq!(loc.name, file_name.len());
    }
    #[test]
    fn test_loc_new_with_directory() {
        let path = PathBuf::from("/");
        let loc = Loc::new(path.clone());
        
        println!("{:?}" , loc) ;
    }
    
    #[test]
    fn test_loc_new_with_empty_path() {
        let path = PathBuf::from("");
        let loc = Loc::new(path);

        // 检查 urn 和 name 是否正确设置为 0
        assert_eq!(loc.urn, 0);
        assert_eq!(loc.name, 0);
    }


}